﻿using System;
using System.Xml;

namespace BuzzX8.Xmpp.StreamElements.Stanza
{
    public class PresenceStanza : Stanza<PresenceStanzaType>
    {
        public static readonly int MinPriorityValue = -127;
        public static readonly int MaxPriorityValue = 128;

        private int? priority;

        public PresenceStanza() : this(PresenceStanzaType.None)
        {}

        public PresenceStanza(PresenceStanzaType type) : base("presence", type)
        {
            priority = null;
        }

        public AvailabilityType Availability { get; set; }

        public int? Priority
        {
            get { return priority; }
            set
            {
                if(value != null && (value.Value > MaxPriorityValue || value.Value < MinPriorityValue))
                {
                    throw new ArgumentException();
                }
                priority = value;
            }
        }

        public string StatusText { get; set; }

        protected override object GetAttributeValueForType(PresenceStanzaType type)
        {
            switch (type)
            {
                case PresenceStanzaType.Error:
                    return "error";

                case PresenceStanzaType.Probe:
                    return "probe";

                case PresenceStanzaType.Subscribe:
                    return "subscribe";

                case PresenceStanzaType.Subscribed:
                    return "subscribed";

                case PresenceStanzaType.None:
                    return "";

                case PresenceStanzaType.Unavailable:
                    return "unavailable";

                case PresenceStanzaType.Unsubscribe:
                    return "unsubscribe";

                case PresenceStanzaType.Unsubscribed:
                    return "unsubscribed";

                default:
                    throw new NotImplementedException();
            }
        }

        protected override void WritePayload(XmlWriter writer)
        {
            base.WritePayload(writer);
            WriteAvailabilityStatus(writer);
            WriteStatusText(writer);
            WritePriority(writer);
        }

        private void WriteAvailabilityStatus(XmlWriter writer)
        {
            if(Availability == AvailabilityType.None) return;
            writer.WriteElementString("show", GetStringForAvailabilityStatus(Availability));
        }

        private string GetStringForAvailabilityStatus(AvailabilityType status)
        {
            switch (Availability)
            {
                case AvailabilityType.None:
                    return "";

                case AvailabilityType.Chat:
                    return "chat";

                case AvailabilityType.Away:
                    return "away";

                case AvailabilityType.ExtendedAway:
                    return "xa";

                case AvailabilityType.DoNotDisturb:
                    return "dnd";

                default:
                    throw new NotImplementedException();
            }
        }

        private void WriteStatusText(XmlWriter writer)
        {
            if (string.IsNullOrEmpty(StatusText)) return;
            writer.WriteElementString("status", StatusText);
        }

        private void WritePriority(XmlWriter writer)
        {
            if (Priority == null) return;
            writer.WriteElementString("priority", Priority.Value.ToString());
        }
    }
}
